package com.flycms.modules.site.service.impl;

import com.flycms.common.pager.Pager;
import com.flycms.common.utils.DateUtils;
import com.flycms.common.utils.RedisUtils;
import com.flycms.common.utils.mark.SnowFlakeUtils;
import com.flycms.common.utils.result.LayResult;
import com.flycms.common.utils.result.Result;
import com.flycms.common.utils.text.Convert;
import com.flycms.modules.company.entity.Company;
import com.flycms.modules.company.service.CompanyService;
import com.flycms.modules.finance.service.OrderService;
import com.flycms.modules.shiro.ShiroUtils;
import com.flycms.modules.site.dao.SiteDao;
import com.flycms.modules.site.entity.Site;
import com.flycms.modules.site.entity.SiteCompany;
import com.flycms.modules.site.entity.SiteVO;
import com.flycms.modules.site.entity.UserSiteVO;
import com.flycms.modules.site.service.SiteService;
import com.flycms.modules.site.service.SiteCompanyService;
import com.flycms.modules.system.dao.ConfigureDao;
import com.flycms.modules.system.entity.Configure;
import com.flycms.modules.system.service.ConfigureService;
import com.flycms.modules.user.entity.User;
import com.flycms.modules.user.service.UserService;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;


import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class SiteServiceImpl implements SiteService {
    private static final Logger log = LoggerFactory.getLogger(SiteServiceImpl.class);

    @Autowired
    private SiteDao siteDao;
    @Autowired
    private SiteCompanyService siteCompanyService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private UserService userService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private ConfigureService systemService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ConfigureDao systemDao;

    // ///////////////////////////////
    // /////       增加       ////////
    // ///////////////////////////////
    /**
     * 添加模块信息
     *
     * @param site
     * @return
     */
    @Transactional
    public Object addSite(Site site) {
        if(this.checkSiteByName(site.getSiteName(),null)){
            return Result.failure("该名称已存在，请重命名或者联系管理员！");
        }
        site.setId(SnowFlakeUtils.nextId());
        if (this.checkSiteByDomain(site.getDomain(),site.getId())){
            return Result.failure("短域名已被占用");
        }
        site.setCreateTime(LocalDateTime.now());
        siteDao.save(site);

        Company company = companyService.findCompanyByUser(ShiroUtils.getLoginUser().getId());
        if (company == null){
            return Result.failure("未完善企业信息，请完善后再添加网站");
        }
        SiteCompany siteCompany=new SiteCompany();
        siteCompany.setCompanyId(company.getId());
        siteCompany.setSiteId(site.getId());
        siteCompanyService.addSiteCompany(siteCompany);
        try {
            FileUtils.copyDirectory(new File("./views/templates/theme/computer/qianzhu"),new File("./views/templates/websiteTemplate"));
        }catch (IOException e) {
            log.error("复制模板文件夹出错");
        }
        return Result.success();
    }

    /**
     * 用户添加网站信息
     *
     * @param site
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Object addUserSite(Site site){
        Company company = companyService.findCompanyByUser(ShiroUtils.getLoginUser().getId());
        if (company == null){
            return Result.failure("未完善企业信息，请完善后再添加网站");
        }
        //系统设置可建立试用网站数量
        Integer probationNumber=Integer.parseInt(systemService.findByKeyCode("user_site_number"));
        System.out.println("差集为：");
        SetView<Long> diff = Sets.difference(siteCompanyService.querySiteIdList(company.getId()), orderService.queryOrderByProductIdList(company.getId(),1));
        for (Long temp : diff) {
            System.out.println(temp);
        }
        if(probationNumber <= diff.size()){
            return Result.failure("您的试用网站数量已达极限，如果有需要请购买使用！");
        }
        if(this.holdSiteByDomain(site.getDomain())){
            return Result.failure("请修改当前网站二级域名，该域名已被平台保留");
        }
        if(this.checkSiteByName(site.getSiteName(),null)){
            return Result.failure("该名称已存在，请重命名或者联系管理员！");
        }
        site.setId(SnowFlakeUtils.nextId());
        if (this.checkSiteByDomain(site.getDomain(),null)){
            return Result.failure("短域名已被占用");
        }
        site.setCreateTime(LocalDateTime.now());
        //网站审核状态
        site.setVerify(Integer.parseInt(systemService.findByKeyCode("user_site_verify")));
        //处理后台设置用户试用时间
        String probation = systemService.findByKeyCode("user_site_probation");
        LocalDateTime localDateTime = LocalDateTime.now();
        if("day".equals(probation)){
            localDateTime = localDateTime.plusYears(1);
        }else if("week".equals(probation)){
            localDateTime = localDateTime.plusYears(7);
        }else if("month".equals(probation)){
            localDateTime.minusMonths(1);
        }else if("year".equals(probation)){
            localDateTime = localDateTime.plusYears(1);
        }
        site.setExpireTime(localDateTime);
        int total = siteDao.save(site);
        if(total > 0){
            SiteCompany siteCompany=new SiteCompany();
            siteCompany.setCompanyId(company.getId());
            siteCompany.setSiteId(site.getId());
            siteCompanyService.addSiteCompany(siteCompany);
            return Result.success("网站添加成功");
        }else{
            return Result.failure("网站添加失败");
        }
    }
    // ///////////////////////////////
    // /////        刪除      ////////
    // ///////////////////////////////
    /**
     * 批量删除网站信息
     *
     * @param ids 需要删除的数据ID
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteSiteByIds(String ids){
        Long[] siteIds = Convert.toLongArray(ids);
        for (Long siteId : siteIds)
        {
            if (!siteCompanyService.checkSiteCompany(siteId)){
                Site site = siteDao.findById(siteId);
                return Result.failure(String.format(site.getSiteName()+"%1$s没有管理权限,不能删除"));
            }
        }
        int totalCount=siteDao.deleteSiteByIds(siteIds);
        if(totalCount > 0) {
            siteCompanyService.deleteSiteCompanyById(siteIds);
            return Result.success();
        }else{
            return Result.failure("删除失败");
        }
    }

    // ///////////////////////////////
    // /////        修改      ////////
    // ///////////////////////////////

    /**
     * 后台更新默认网站信息
     *
     * @param site
     * @return
     */
    @Transactional
    @CacheEvict(value="sites", beforeInvocation=true)
    public Object updateAdminSiteById(Site site){
        if(this.checkSiteByName(site.getSiteName(),site.getId())){
            return Result.failure("网站名称已被占用");
        }
        if (this.checkSiteByDomain(site.getDomain(),site.getId())){
            return Result.failure("短域名已被占用");
        }
        siteDao.updateSiteById(site);
        return Result.success();
    }

    @Transactional
    //@CacheEvict(value="sites", beforeInvocation=true)
    public Object updateSiteById(Site site){
        if(this.holdSiteByDomain(site.getDomain())){
            return Result.failure("请修改当前网站二级域名，该域名已被平台保留");
        }
        if(this.checkSiteByName(site.getSiteName(),site.getId())){
            return Result.failure("网站名称已被占用");
        }
        if (this.checkSiteByDomain(site.getDomain(),site.getId())){
            return Result.failure("短域名已被占用");
        }
        siteDao.updateSiteById(site);
        return Result.success();
    }

    /**
     * 更新网站开关状态
     *
     * @param status
     * @param id
     * @return
     */
    @Transactional
    //@CacheEvict(value="sites", beforeInvocation=true)
    public Object updateSiteByStatus(Boolean status,Long id){
        Site site =new Site();
        site.setId(id);
        site.setStatus(status);
        siteDao.updateSiteById(site);
        return Result.success();
    }
    // ///////////////////////////////
    // /////        查詢      ////////
    // ///////////////////////////////

    /**
     * 查询当前用户网站名称是否重名
     *
     * @param siteName
     * @return
     */
    public boolean checkSiteByName(String siteName,Long id) {
        int totalCount = siteDao.checkSiteByName(siteName,id);
        return totalCount > 0 ? true : false;
    }

    /**
     * 查询当前用户网站名称是否重名
     *
     * @param domain
     * @return
     */
    public boolean checkSiteByDomain(String domain,Long id) {
        int totalCount = siteDao.checkSiteByDomain(domain,id);
        return totalCount > 0 ? true : false;
    }

    /**
     * 检查域名是否已保护
     *
     * @param domain
     * @return
     */
    public boolean holdSiteByDomain(String domain){
        String kbbeUser=systemService.findByKeyCode("hold_domain");
        if(kbbeUser!=null){
            String[] notallow = kbbeUser.split(","); //转换为数组
            for (String s : notallow) {
                if (s.equals(domain)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 检查是否是默认官网域名
     *
     * @param domain
     * @return
     */
    public boolean defaultSiteByDomain(String domain){
        String kbbeUser=systemService.findByKeyCode("default_site_domain");
        if(kbbeUser!=null){
            String[] notallow = kbbeUser.split(","); //转换为数组
            for (String s : notallow) {
                if (s.equals(domain)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 按id查询网站信息
     *
     * @param id
     * @return
     */
    //@Cacheable(value="sites",key="'site_'+#id")
    public Site findById(Long id){
        return siteDao.findById(id);
    }

    /**
     * 按网站Domain查询网站信息
     *
     * @param domain
     * @return
     */
    //@Cacheable(value="sites",key="'siteDomain_'+#domain")
    public Site findByDomain(String domain){
        return siteDao.findByDomain(domain);
    }

    /**
     * 短域名查询网站id
     *
     * @param domain
     * @return
     */
    //@Cacheable(value="sites",key="'siteId_'+#domain")
    public Long findSiteByDomain(String domain) {
        Site site = siteDao.findByDomain(domain);
        if(site == null){
            return null;
        }
        return site.getId();
    }

    //@Cacheable(value="system",key="'key_'+#keyCode")
    public String findByKeyCode(String keyCode){
        Configure system=systemDao.findByKeyCode(keyCode);
        if(system != null){
            return system.getKeyValue();
        }
        return null;
    }

    /**
     * 按网站id和用户id查询网站信息
     *
     * @param siteId
     *         网站id
     * @param companyId
     *         用户id
     * @return
     */
    public Site findSiteByCompanyId(Long siteId,Long companyId){
        return siteDao.findSiteByCompanyId(siteId,companyId);
    }

    /**
     * 管理员查看所有网站翻页列表
     *
     * @param site
     *         根据分类名查询
     * @param page
     * @param pageSize
     * @param sort
     * @param order
     * @return
     */
    public Object selectSiteListPager(Site site, Integer page, Integer pageSize, String sort, String order) {
        StringBuffer whereStr = new StringBuffer(" 1 = 1");
        if (!StringUtils.isEmpty(site.getSiteName())) {
            whereStr.append(" and site_name like concat('%',#{entity.siteName},'%')");
        }
        whereStr.append(" and deleted = 0");

        Pager<Site> pager = new Pager(page, pageSize);
        //排序设置
        if (!StringUtils.isEmpty(sort)) {
            Boolean rank = "desc".equals(order) ? true : false;
            pager.addOrderProperty(sort, rank,true);
        }
        //使用limit进行查询翻页
        pager.addLimitProperty(true);
        //查询条件
        Site entity = new Site();
        entity.setSiteName(site.getSiteName());
        pager.setEntity(entity);
        pager.setWhereStr(whereStr.toString());
        List<Site> sitelsit = siteDao.queryList(pager);
        List<SiteVO> volsit = new ArrayList<SiteVO>();
        sitelsit.forEach(enttity -> {
            SiteVO siteVo = new SiteVO();
            siteVo.setId(enttity.getId());
            siteVo.setSiteName(enttity.getSiteName());
            siteVo.setDomain(enttity.getDomain());
            User user=siteDao.selectSiteUserBySiteId(enttity.getId());
            if(user!=null){
                siteVo.setUserId(user.getId());
                siteVo.setNickname(user.getNickname());
            }else{
                siteVo.setUserId(null);
                siteVo.setNickname("暂无用户");
            }
            siteVo.setCreateTime(enttity.getCreateTime());
            siteVo.setExpireTime(enttity.getExpireTime());
            siteVo.setStatus(enttity.getStatus());
            volsit.add(siteVo);
        });
        return LayResult.success(0, "true", siteDao.queryTotal(pager), volsit);
    }

    /**
     * 企业用户所有网站翻页列表
     *
     * @param site
     *         根据分类名查询
     * @param page
     * @param pageSize
     * @param sort
     * @param order
     * @return
     */
    public Object selectCompanySiteListPager(Site site, Integer page, Integer pageSize, String sort, String order) {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        MapperFacade mapper = mapperFactory.getMapperFacade();
        StringBuffer whereStr = new StringBuffer(" 1 = 1");
        if (!StringUtils.isEmpty(site.getSiteName())) {
            whereStr.append(" and s.site_name like concat('%',#{entity.siteName},'%')");
        }
        whereStr.append(" and s.deleted = 0");
        whereStr.append(" and su.company_id = #{entity.companyId}");
        Pager<Site> pager = new Pager(page, pageSize);
        //排序设置
        if (!StringUtils.isEmpty(sort)) {
            Boolean rank = "desc".equals(order) ? true : false;
            pager.addOrderProperty(sort, rank,true);
        }
        //使用limit进行查询翻页
        pager.addLimitProperty(true);
        //查询条件
        Site entity = new Site();
        entity.setSiteName(site.getSiteName());
        Company company=companyService.findCompanyByUser(ShiroUtils.getLoginUser().getId());
        if(company!=null){
            entity.setCompanyId(company.getId());
        }
        pager.setEntity(entity);
        pager.setWhereStr(whereStr.toString());
        List<Site> sitelsit = siteDao.queryUserSiteByList(pager);
        return LayResult.success(0, "true", siteDao.queryUserSiteByTotal(pager), mapper.mapAsList(sitelsit,UserSiteVO.class));
    }

    /**
     * 查询用户拥有的所有网站数量
     *
     * @return
     */
    public int selectCompanySiteTotal() {
        StringBuffer whereStr = new StringBuffer(" 1 = 1");
        whereStr.append(" and s.deleted = 0");
        whereStr.append(" and su.company_id = #{entity.companyId}");
        Pager<Site> pager = new Pager();
        //排序设置
        pager.addOrderProperty(null, false,false);
        //使用limit进行查询翻页
        pager.addLimitProperty(false);
        //查询条件
        Site entity = new Site();
        Company company=companyService.findCompanyByUser(ShiroUtils.getLoginUser().getId());
        entity.setCompanyId(company.getId());
        pager.setEntity(entity);
        pager.setWhereStr(whereStr.toString());
        return siteDao.queryUserSiteByTotal(pager);
    }

    /**
     * 查询用户所有网站列表
     *
     * @return
     */
    public List<UserSiteVO> selectCompanySiteList() {
        //javabean 映射工具
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        MapperFacade mapper = mapperFactory.getMapperFacade();

        StringBuffer whereStr = new StringBuffer(" 1 = 1");
        whereStr.append(" and s.deleted = 0");
        whereStr.append(" and su.company_id = #{entity.companyId}");
        Pager<Site> pager = new Pager();
        //排序设置
        pager.addOrderProperty(null, false,false);
        //使用limit进行查询翻页
        pager.addLimitProperty(false);
        //查询条件
        Site entity = new Site();
        Company company=companyService.findCompanyByUser(ShiroUtils.getLoginUser().getId());
        entity.setCompanyId(company.getId());
        pager.setEntity(entity);
        pager.setWhereStr(whereStr.toString());
        List<Site> sitelsit = siteDao.queryUserSiteByList(pager);
        return mapper.mapAsList(sitelsit,UserSiteVO.class);
    }
}
